﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace MAS.Web.UI.WebControls
{
    public partial class Chart : System.Web.UI.UserControl
    {
        #region enum ChartType
        public enum ChartType
        {
            Line = 1,
            Column = 2,
            Area = 3,
            Bar = 4
        }
        #endregion

        VerticalAlign _Legend_VAlign = VerticalAlign.Middle;
        public VerticalAlign Legend_VAlign
        {
            get
            {
                return _Legend_VAlign;
            }
            set
            {
                _Legend_VAlign = value;
            }
        }

        HorizontalAlign _Legend_HAlign = HorizontalAlign.Right;
        public HorizontalAlign Legend_HAlign
        {
            get
            {
                return _Legend_HAlign;
            }
            set
            {
                _Legend_HAlign = value;
            }
        }

        private bool _Legend_Enabled = true;
        public bool Legend_Enabled
        {
            get { return _Legend_Enabled; }
            set { _Legend_Enabled = value; }
        }

        public string Title { get; set; }

        public string SubTitle { get; set; }

        public string YAxis { get; set; }

        Collection<object> _XAxisData;
        public Collection<object> XAxisData
        {
            get
            {
                if (_XAxisData == null)
                    _XAxisData = new Collection<object>();

                return _XAxisData;
            }
        }

        private int _XAxisRotation = 0;
        public int XAxisRotation
        {
            get { return _XAxisRotation; }
            set { _XAxisRotation = value; }
        }

        private bool _XAxisEnabled = true;
        public bool XAxisEnabled
        {
            get { return _XAxisEnabled; }
            set { _XAxisEnabled = value; }
        }

        public bool ShowLables { get; set; }

        public string YUnit { get; set; }

        public ChartType Type { get; set; }

        public string Width { get; set; }

        public string Height { get; set; }

        Collection<Series> _ChartSeries;
        public Collection<Series> ChartSeries
        {
            get
            {
                if (_ChartSeries == null)
                    _ChartSeries = new Collection<Series>();

                return _ChartSeries;
            }
        }

        private string _SeriesToolTip;
        public string SeriesToolTip
        {
            get
            {
                if (string.IsNullOrEmpty(_SeriesToolTip))
                    _SeriesToolTip = "'<b>' + this.series.name + '</b><br/>' + this.x + ': ' + this.y + '" + YUnit + "'";
                return _SeriesToolTip;
            }
            set
            {
                _SeriesToolTip = value;
            }
        }

        private bool _EnabelChangeChartType = true;
        public bool EnabelChangeChartType
        {
            get { return _EnabelChangeChartType; }
            set { _EnabelChangeChartType = value; }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            divChangeChartType.Visible = EnabelChangeChartType;
        }

        public void BindChart()
        {
            if (EnabelChangeChartType)
            {
                imgLine.Visible =
                imgColumn.Visible =
                imgArea.Visible =
                imgBar.Visible = true;

                switch (this.Type)
                {
                    case ChartType.Line:
                        imgLine.Visible = false;
                        break;
                    case ChartType.Column:
                        imgColumn.Visible = false;
                        break;
                    case ChartType.Area:
                        imgArea.Visible = false;
                        break;
                    case ChartType.Bar:
                        imgBar.Visible = false;
                        break;
                    default:
                        break;
                }
            }

            string script = string.Empty;

            script = "var chart_" + ClientID + "; var option_" + ClientID + @" = {
        chart: {
            renderTo: '" + divContent.ClientID + @"',
            zoomType : 'x,y',
            type: '" + TypeString() + @"',
            height : '" + Height + @"',
            backgroundColor: '#FFFFFF'," +
            (string.IsNullOrEmpty(this.Width) ? string.Empty : (string.Format("width : {0},", this.Width))) +
            @"style:{
                fontSize : '11px',
                fonrFamily : 'Tahoma'
            }
        },
        title: {
            text: '" + Title + @"',
            x: -20 //center
        },
        subtitle: {
            text: '" + SubTitle + @"',
            x: -20
        },
        xAxis: {
            categories: [],
            labels: {
                align : 'right',
                rotation: " + XAxisRotation.ToString() + @",
                enabled : " + (XAxisEnabled ? "true" : "false") + @"
            }
        },
        exporting: {
            buttons: {
                exportButton: {
                    enabled : false
                },
                printButton: {
                    enabled : false
                }
            }
        },
        yAxis: {
            title: {
                text: '" + YAxis + @"'
            },
            plotLines: [{
                value: 0,
                width: 1,
                color: '#808080'
            }],
            labels: {
                formatter : function () {
                    return this.value;
                }
            }
        },
        tooltip: {
            formatter: function () {
                return " + SeriesToolTip + @";
            }
        },
        legend: {
            layout: 'vertical',
            align: '" + Legend_HAlign.ToString().ToLower() + @"',
            verticalAlign: '" + Legend_VAlign.ToString().ToLower() + @"',
            borderWidth: 1,
            shadow : true,
            enabled : " + (Legend_Enabled ? "true" : "false") + @"
        },
        series: []
    };";

            foreach (object item in XAxisData.OrderBy(c => c))
                script += string.Format(@"
option_{0}.xAxis.categories.push('{1}');", ClientID, item);

            foreach (Series s in ChartSeries)
            {
                string dataString = string.Empty;
                foreach (object item in s.Data)
                    dataString += (item == DBNull.Value ? "null" : item.ToString()) + ",";
                if (dataString.Length > 0)
                    dataString = dataString.Substring(0, dataString.Length - 1);

                script += "option_" + ClientID + ".series.push({name : '" + s.Name + "', data : [" + dataString + @"], 
                " + GetColorString(s.Color) + @"
                dataLabels: {
                    enabled: " + (ShowLables ? "true" : "false") + @",
                    rotation: 0,
                    formatter: function () {
                        return this.y;
                    },
                    style: {
                        fontSize: '11px',
                        fontFamily: 'Tahoma'
                    }
                }});";
            }

            script += "chart_" + ClientID + " = new Highcharts.Chart(option_" + ClientID + ");";

            ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(), script, true);
        }

        private string GetColorString(System.Drawing.Color color)
        {
            string c = string.Empty;
            if (color.IsEmpty)
                return string.Empty;

            if (color.IsKnownColor)
                c = color.Name;
            else if (color.IsNamedColor)
                c = color.Name;
            else
                c = "#" + color.Name.Remove(0, 2);

            return string.Format("color : '{0}',", c);
        }

        protected string TypeString()
        {
            switch (this.Type)
            {
                case ChartType.Line:
                    return "spline";
                case ChartType.Column:
                    return "column";
                case ChartType.Area:
                    return "area";
                case ChartType.Bar:
                    return "bar";
                default:
                    return string.Empty;
            }
        }

        public event EventHandler<EventArgs> ChartTypeChanged;

        void OnChartTypeChanged()
        {
            if (ChartTypeChanged != null)
                ChartTypeChanged(this, EventArgs.Empty);
        }

        protected void imgBar_Click(object sender, ImageClickEventArgs e)
        {
            this.Type = ChartType.Bar;
            OnChartTypeChanged();
        }

        protected void imgColumn_Click(object sender, ImageClickEventArgs e)
        {
            this.Type = ChartType.Column;
            OnChartTypeChanged();
        }

        protected void imgArea_Click(object sender, ImageClickEventArgs e)
        {
            this.Type = ChartType.Area;
            OnChartTypeChanged();
        }

        protected void imgLine_Click(object sender, ImageClickEventArgs e)
        {
            this.Type = ChartType.Line;
            OnChartTypeChanged();
        }

        public class Series
        {
            public Series()
            {
                Data = new Collection<object>();
            }

            public Series(string name)
            {
                Name = name;
                Data = new Collection<object>();
            }

            public Series(string name, System.Drawing.Color color)
            {
                Name = name;
                Color = color;
                Data = new Collection<object>();
            }

            public System.Drawing.Color Color { get; set; }

            public string Name { get; set; }
            public Collection<object> Data { get; private set; }
        }
    }
}